前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# 逐行读取 readline

30 秒速记

  • readline.createInterface({ input, crlfDelay: Infinity }) 把任意可读流按行切开
  • 逐行读大文件:for await (const line of rl),内存只占当前行
  • crlfDelay: Infinity 保证 \r\n 被当成一个换行,Windows 文件不会多出空行
  • 交互式命令行用 readline/promises 的 rl.question()(Node 17 起)
  • 处理 Ctrl+C 监听 SIGINT,Ctrl+D / 输入结束会触发 close;非终端环境 process.stdin.isTTY 为 undefined

readline 就是给可读流装一把「按行切」的刀,常用在两个场景:逐行读大文件,和命令行里跟用户一问一答。 读大文件时用 createInterface 包住 fs.createReadStream,再 for await 一行一行处理,几个 GB 的日志内存也就占一行的大小。记得加 crlfDelay: Infinity,否则 Windows 换行可能被拆成两次。交互场景用 readline/promises 的 question(),配合 await 写起来很顺;用完一定要 rl.close(),不然进程会一直挂着等输入。

理解「逐行读取 readline」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

readline 的两种典型用法,各给一段能直接跑的代码。

逐行读文件:

const fs = require('fs');
const readline = require('readline');

async function countErrors(file) {
  const rl = readline.createInterface({
    input: fs.createReadStream(file),
    crlfDelay: Infinity,   // \r\n 当作一个换行
  });
  let total = 0, errors = 0;
  for await (const line of rl) {
    total++;
    if (line.includes('ERROR')) errors++;
  }
  return { total, errors };   // 读完 rl 会自动 close
}

countErrors('app.log').then(console.log);  // { total: 10234, errors: 17 }
@前端进阶之旅: 代码已经复制到剪贴板

命令行交互(Node 17 起有 readline/promises):

const readline = require('readline/promises');

async function main() {
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
  rl.on('SIGINT', () => { rl.close(); process.exitCode = 130; });  // Ctrl+C

  const name = await rl.question('项目名称:');
  console.log(`创建 ${name}`);
  rl.close();   // 不关的话进程会一直等输入
}
main();
@前端进阶之旅: 代码已经复制到剪贴板

几个容易忽略的地方:逐行读取的输入源出错时,for await 不一定能接住底层文件流的错误,最好单独给文件流监听 error;交互脚本要考虑被管道或 CI 调用的情况,先看 process.stdin.isTTY;输入密码这类敏感信息时,readline 默认会回显,需要自己处理静音输出或者用 @inquirer/prompts 这类库。

面试官追问

追问 1一个 5GB 的日志文件要统计 ERROR 行数,怎么写?
参考回答

createInterface({ input: fs.createReadStream(file), crlfDelay: Infinity }),然后 for await (const line of rl) if (line.includes('ERROR')) n++。内存只跟单行长度有关。

追问 2命令行工具问完问题、打印结果了,进程却不退出,为什么?
参考回答

readline 接口还开着,一直在等 stdin 的输入。处理完要调 rl.close(),for await 正常读完时会自动关,但 question() 这种交互模式必须自己关。

追问 3同一个脚本在 CI 里跑卡住了,本地终端正常,可能是什么原因?
参考回答

CI 里 stdin 不是终端,没人输入也没有结束信号,question() 就一直等。先判断 process.stdin.isTTY,非交互环境改从参数或环境变量读,或者直接给默认值。

追问 4用户在提问时按了 Ctrl+C,怎么优雅地退出?
参考回答

rl.on('SIGINT', () => { rl.close(); process.exitCode = 130; }),在回调里做清理。没有这个监听的话,按下 Ctrl+C 后输入流会被暂停,行为不一定是你想要的。

追问 5导入一个文件,有一行有几百 MB 长,readline 扛得住吗?
参考回答

扛不住,readline 会把整行攒在内存里才吐出来。不可信的输入要先限制单行长度,或者改用自己写的 Transform 在超长时直接报错。

# 模块概览

30 秒速记

  • readline = 把一个可读流按「行」切好喂给你,输入源可以是键盘也可以是文件
  • 三类典型用途:日志逐行分析 / Tab 自动补全 / npm init 那种问答式脚手架
  • 核心对象是 readline.createInterface({ input, output }),键盘交互接 process.stdin / process.stdout,读文件就接 fs.createReadStream
  • 用完记得 rl.close(),不关的话 stdin 一直挂着,进程不退出
  • 新版本有 readline/promises(Node 17+),await rl.question() 写问答比回调顺手

readline 就是 Node.js 自带的「按行读输入」工具,输入从哪来它不管,键盘、文件、管道都行。 你可以把它理解成一个切行器:底下是一条字节流,它帮你按换行符切好,每切出一行就通知你一次。所以同一个模块既能做日志分析,一行一行处理大文件不占内存;也能做命令行交互,比如问一句答一句的脚手架、按 Tab 出提示。小工具我一般直接用它,问题多、要选择列表了才上 inquirer 这类库。

readline是个非常实用的模块。如名字所示,主要用来实现逐行读取,比如读取用户输入,或者读取文件内容。常见使用场景有下面几种,本文会逐一举例说明。

  • 文件逐行读取:比如说进行日志分析。
  • 自动完成:比如输入npm,自动提示"help init install"。
  • 命令行工具:比如npm init这种问答式的脚手架工具。

面试官追问

追问 1readline 这名字听着像读东西的,是不是只能用来读文件?
参考回答

不是。它只认「输入流」,键盘对应 process.stdin,文件对应 fs.createReadStream(),管道进来的也是流。它真正的重点是「按行」处理。

追问 2脚本问完问题、打印完结果,终端还卡着不退出,为什么?
参考回答

大概率没调 rl.close()。接口开着就会一直监听 stdin,事件循环里还有活,进程自然不退。问答流程结束的地方补一句 rl.close() 就好。

追问 3这个脚手架放到 CI 里跑就一直挂着,怎么办?
参考回答

CI 没有人在终端前回答问题,question 会一直等。脚手架要支持参数或配置文件跳过问答,比如 --yes 全用默认值,或者检测 process.stdin.isTTY 为假时直接走非交互模式。

追问 4读几个 G 的日志,用 fs.readFileSync 再 split('\n') 行不行?
参考回答

文件小可以,几个 G 不行,一次全读进内存可能直接 OOM,字符串长度也有上限。用 readline 接文件流,读一行处理一行,内存占用基本恒定。

追问 5问答式工具什么时候该换成 inquirer 这种库?
参考回答

只有几个文本问题时 readline 够用、零依赖。要单选多选、方向键选择、输入校验和重试,自己写就是在重造轮子,直接上库更省事。

# 基础例子

30 秒速记

  • 套路三步:createInterface 建接口 → rl.question(提示, 回调) 拿一行输入 → 回调里处理完 rl.close()
  • input 接 process.stdin、output 接 process.stdout,提示语写到 output 上
  • question 是异步的:用户敲回车才进回调,拿到的是整行字符串,不做任何校验
  • 空输入是 ''
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
      • 模块概览
      • 基础例子
      • 例子:文件逐行读取:日志分析
      • 例子:自动完成:代码提示
      • 例子:命令行工具:npmt init
      • 写在后面
      • 相关链接
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

逐行读取 readline|Nodejs专题系列

# 逐行读取 readline

30 秒速记

  • readline.createInterface({ input, crlfDelay: Infinity }) 把任意可读流按行切开
  • 逐行读大文件:for await (const line of rl),内存只占当前行
  • crlfDelay: Infinity 保证 \r\n 被当成一个换行,Windows 文件不会多出空行
  • 交互式命令行用 readline/promises 的 rl.question()(Node 17 起)
  • 处理 Ctrl+C 监听 SIGINT,Ctrl+D / 输入结束会触发 close;非终端环境 process.stdin.isTTY 为 undefined

readline 就是给可读流装一把「按行切」的刀,常用在两个场景:逐行读大文件,和命令行里跟用户一问一答。 读大文件时用 createInterface 包住 fs.createReadStream,再 for await 一行一行处理,几个 GB 的日志内存也就占一行的大小。记得加 crlfDelay: Infinity,否则 Windows 换行可能被拆成两次。交互场景用 readline/promises 的 question(),配合 await 写起来很顺;用完一定要 rl.close(),不然进程会一直挂着等输入。

理解「逐行读取 readline」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

readline 的两种典型用法,各给一段能直接跑的代码。

逐行读文件:

const fs = require('fs');
const readline = require('readline');

async function countErrors(file) {
  const rl = readline.createInterface({
    input: fs.createReadStream(file),
    crlfDelay: Infinity,   // \r\n 当作一个换行
  });
  let total = 0, errors = 0;
  for await (const line of rl) {
    total++;
    if (line.includes('ERROR')) errors++;
  }
  return { total, errors };   // 读完 rl 会自动 close
}

countErrors('app.log').then(console.log);  // { total: 10234, errors: 17 }
@前端进阶之旅: 代码已经复制到剪贴板

命令行交互(Node 17 起有 readline/promises):

const readline = require('readline/promises');

async function main() {
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
  rl.on('SIGINT', () => { rl.close(); process.exitCode = 130; });  // Ctrl+C

  const name = await rl.question('项目名称:');
  console.log(`创建 ${name}`);
  rl.close();   // 不关的话进程会一直等输入
}
main();
@前端进阶之旅: 代码已经复制到剪贴板

几个容易忽略的地方:逐行读取的输入源出错时,for await 不一定能接住底层文件流的错误,最好单独给文件流监听 error;交互脚本要考虑被管道或 CI 调用的情况,先看 process.stdin.isTTY;输入密码这类敏感信息时,readline 默认会回显,需要自己处理静音输出或者用 @inquirer/prompts 这类库。

面试官追问

追问 1一个 5GB 的日志文件要统计 ERROR 行数,怎么写?
参考回答

createInterface({ input: fs.createReadStream(file), crlfDelay: Infinity }),然后 for await (const line of rl) if (line.includes('ERROR')) n++。内存只跟单行长度有关。

追问 2命令行工具问完问题、打印结果了,进程却不退出,为什么?
参考回答

readline 接口还开着,一直在等 stdin 的输入。处理完要调 rl.close(),for await 正常读完时会自动关,但 question() 这种交互模式必须自己关。

追问 3同一个脚本在 CI 里跑卡住了,本地终端正常,可能是什么原因?
参考回答

CI 里 stdin 不是终端,没人输入也没有结束信号,question() 就一直等。先判断 process.stdin.isTTY,非交互环境改从参数或环境变量读,或者直接给默认值。

追问 4用户在提问时按了 Ctrl+C,怎么优雅地退出?
参考回答

rl.on('SIGINT', () => { rl.close(); process.exitCode = 130; }),在回调里做清理。没有这个监听的话,按下 Ctrl+C 后输入流会被暂停,行为不一定是你想要的。

追问 5导入一个文件,有一行有几百 MB 长,readline 扛得住吗?
参考回答

扛不住,readline 会把整行攒在内存里才吐出来。不可信的输入要先限制单行长度,或者改用自己写的 Transform 在超长时直接报错。

# 模块概览

30 秒速记

  • readline = 把一个可读流按「行」切好喂给你,输入源可以是键盘也可以是文件
  • 三类典型用途:日志逐行分析 / Tab 自动补全 / npm init 那种问答式脚手架
  • 核心对象是 readline.createInterface({ input, output }),键盘交互接 process.stdin / process.stdout,读文件就接 fs.createReadStream
  • 用完记得 rl.close(),不关的话 stdin 一直挂着,进程不退出
  • 新版本有 readline/promises(Node 17+),await rl.question() 写问答比回调顺手

readline 就是 Node.js 自带的「按行读输入」工具,输入从哪来它不管,键盘、文件、管道都行。 你可以把它理解成一个切行器:底下是一条字节流,它帮你按换行符切好,每切出一行就通知你一次。所以同一个模块既能做日志分析,一行一行处理大文件不占内存;也能做命令行交互,比如问一句答一句的脚手架、按 Tab 出提示。小工具我一般直接用它,问题多、要选择列表了才上 inquirer 这类库。

readline是个非常实用的模块。如名字所示,主要用来实现逐行读取,比如读取用户输入,或者读取文件内容。常见使用场景有下面几种,本文会逐一举例说明。

  • 文件逐行读取:比如说进行日志分析。
  • 自动完成:比如输入npm,自动提示"help init install"。
  • 命令行工具:比如npm init这种问答式的脚手架工具。

面试官追问

追问 1readline 这名字听着像读东西的,是不是只能用来读文件?
参考回答

不是。它只认「输入流」,键盘对应 process.stdin,文件对应 fs.createReadStream(),管道进来的也是流。它真正的重点是「按行」处理。

追问 2脚本问完问题、打印完结果,终端还卡着不退出,为什么?
参考回答

大概率没调 rl.close()。接口开着就会一直监听 stdin,事件循环里还有活,进程自然不退。问答流程结束的地方补一句 rl.close() 就好。

追问 3这个脚手架放到 CI 里跑就一直挂着,怎么办?
参考回答

CI 没有人在终端前回答问题,question 会一直等。脚手架要支持参数或配置文件跳过问答,比如 --yes 全用默认值,或者检测 process.stdin.isTTY 为假时直接走非交互模式。

追问 4读几个 G 的日志,用 fs.readFileSync 再 split('\n') 行不行?
参考回答

文件小可以,几个 G 不行,一次全读进内存可能直接 OOM,字符串长度也有上限。用 readline 接文件流,读一行处理一行,内存占用基本恒定。

追问 5问答式工具什么时候该换成 inquirer 这种库?
参考回答

只有几个文本问题时 readline 够用、零依赖。要单选多选、方向键选择、输入校验和重试,自己写就是在重造轮子,直接上库更省事。

# 基础例子

30 秒速记

  • 套路三步:createInterface 建接口 → rl.question(提示, 回调) 拿一行输入 → 回调里处理完 rl.close()
  • input 接 process.stdin、output 接 process.stdout,提示语写到 output 上
  • question 是异步的:用户敲回车才进回调,拿到的是整行字符串,不做任何校验
  • 空输入是 '',多个单词也照样给你,要什么格式自己校验
  • Node 17+ 可以 require('readline/promises'),直接 const answer = await rl.question(...)

这个例子就是 readline 最基础的用法:问一句,等用户回车,拿到整行文本再处理。 rl.question 先把提示打印到 output,用户敲回车后回调收到那一整行,例子里 answer.toUpperCase() 转大写再打印。要注意它只负责「拿到一行」,用户输空串、输一句话都会原样给你,想限制成一个单词得自己判断。最后一定要 rl.close(),不然 stdin 还开着,程序停在那不退出。新版 Node 我更习惯用 promises 版本:

const readline = require('readline/promises');
(async () => {
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
  const answer = await rl.question('Please input a word: ');
  console.log('You have entered [%s]', answer.toUpperCase()); // 输入 hello → [HELLO]
  rl.close();
})();
@前端进阶之旅: 代码已经复制到剪贴板

← 6.1 流操作 stream7.1 进程相关 process →

fe